package com.sz.biz.logistics.bill.service.impl;

import com.google.common.collect.Lists;
import com.sz.biz.common.AbstractVersionEntityService;
import com.sz.biz.logistics.bill.dto.*;
import com.sz.biz.logistics.bill.entity.BillingTask;
import com.sz.biz.logistics.bill.entity.BillingTaskStatus;
import com.sz.biz.logistics.bill.service.BillingOrderRelService;
import com.sz.biz.logistics.bill.service.BillingService;
import com.sz.biz.logistics.bill.service.BillingTaskService;
import com.sz.biz.logistics.constants.ErrorCodes;
import com.sz.biz.logistics.ord.entity.OrdServiceBill;
import com.sz.biz.logistics.ord.service.OrdServiceBillService;
import com.sz.biz.trade.constants.TrdConstants;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.CommonModel;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.utils.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Function: 账单任务服务<br>
 * Author: jifeixing <br>
 * Date: 2017-05-17 14:10:00
 */
@Service("billingTaskService")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class BillingTaskServiceImpl extends AbstractVersionEntityService implements BillingTaskService {

    @Autowired
    private BillingService billingService;
    @Autowired
    private BillingOrderRelService billingOrderRelService;
    @Autowired
    private OrdServiceBillService ordServiceBillService;

    /**
     * 根据任务编码删除任务
     *
     * @param taskCodes
     */
    @Override
    public void batchdeleteByTaskCode(List<String> taskCodes, String type) {
        ParamData paramData = new ParamData();
        paramData.put("taskCodes", taskCodes);
        paramData.put("type", type);
        //只能删除已完成状态的任务
        checkSatusPreDelete(paramData);
        dao.update(getSqlName("batchdeleteByTaskCode"), paramData);
    }

    /**
     * 只能删除已完成的任务
     *
     * @param paramData
     */
    private void checkSatusPreDelete(ParamData paramData) {
        List<BillingTask> billingTasks = dao.findForList(getSqlName("findByTaskCodes"), paramData, BillingTask.class);
        if (null != billingTasks && billingTasks.size() > 0) {
            for (BillingTask billingTask : billingTasks) {
                if (!BillingTaskStatus.COMPLETED.getCode().equals(billingTask.getTaskStatus().getCode())) {
                    throw Exceptions.bizException(ErrorCodes.ERROR_FINANCIAL_COMPLETE_CAN_DELETE);
                }
            }
        }
    }

    /**
     * 确认生成账单提示信息
     *
     * @param billingTaskQueryDto
     * @return
     */
    @Override
    public BillingDto preGenerateBill(BillingTaskQueryDto billingTaskQueryDto) {
        BillingDto billingDto = new BillingDto();
        try {
            //验证参数
            validateStartEndTime(billingTaskQueryDto);
            //获取要生成的账单的信息
            List<Integer> customerId = billingTaskQueryDto.getCustomerIds();
            BillingDto billingDtoReturn = new BillingDto();
            if (TrdConstants.BillType.PAYABLE.equals(billingTaskQueryDto.getType())) {
                billingDtoReturn = ordServiceBillService.preGenerateCustomerBilling(billingTaskQueryDto.getCustomerIds(), billingTaskQueryDto.getStartEffectTime(), billingTaskQueryDto.getEndEffectTime(), billingTaskQueryDto.getType());
            } else {
                billingDtoReturn = ordServiceBillService.preGenerateSupplierBilling(billingTaskQueryDto.getCustomerIds(), billingTaskQueryDto.getStartEffectTime(), billingTaskQueryDto.getEndEffectTime(), billingTaskQueryDto.getType());
            }
            if (null != billingDtoReturn) {
                if (null == billingDtoReturn.getCustomerIds() || billingDtoReturn.getCustomerIds() <= 0) {
                    billingDto.setCustomerIds(0);
                } else {
                    billingDto.setCustomerIds(billingDtoReturn.getCustomerIds());
                }
                if (null == billingDtoReturn.getOrderCounts() || billingDtoReturn.getOrderCounts() <= 0) {
                    billingDto.setOrderCounts(0);
                } else {
                    billingDto.setOrderCounts(billingDtoReturn.getOrderCounts());
                }

            }
            billingDto.setStartEffectTime(billingTaskQueryDto.getStartEffectTime());
            billingDto.setEndEffectTime(billingTaskQueryDto.getEndEffectTime());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return billingDto;
    }

    /**
     * 生成账单
     *
     * @param billingTaskQueryDto
     */
    @Override
    public String generateBill(BillingTaskQueryDto billingTaskQueryDto) {
        //判断所选账单周期内价钱是否有汇率转换
        if (billingTaskQueryDto != null && billingTaskQueryDto.getType() != null) {
            if (TrdConstants.BillType.PAYABLE.equals(billingTaskQueryDto.getType())) {
                isExchangeRateEror(billingTaskQueryDto);
            }
        }
        //任务编码
        String taskCode = generateTaskCode();
        //任务开始时间s
        Date taskStartTime = dao.getDbDate();
        //获取(用户)时间段内的所有订单
        BillingDto billingDtoReturn = new BillingDto();
        if (TrdConstants.BillType.PAYABLE.equals(billingTaskQueryDto.getType())) {
            billingDtoReturn = ordServiceBillService.preGenerateCustomerBilling(billingTaskQueryDto.getCustomerIds(), billingTaskQueryDto.getStartEffectTime(), billingTaskQueryDto.getEndEffectTime(), billingTaskQueryDto.getType());
        } else {
            billingDtoReturn = ordServiceBillService.preGenerateSupplierBilling(billingTaskQueryDto.getCustomerIds(), billingTaskQueryDto.getStartEffectTime(), billingTaskQueryDto.getEndEffectTime(), billingTaskQueryDto.getType());
        }
        if (null != billingDtoReturn && billingDtoReturn.getOrderCounts() > 0) {
            //创建一个线程池
            ExecutorService cachedThreadPool = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                    60L, TimeUnit.SECONDS,
                    new SynchronousQueue<Runnable>());

            cachedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    List<String> taskCodes = null;
                    try {
                        taskCodes = generateThread(billingTaskQueryDto, taskCode, taskStartTime);
                        if (null != taskCodes && taskCodes.size() > 0) {
                            //所有账单生成完毕，任务更新为完成状态
                            updateTaskStatus(BillingTaskStatus.COMPLETED, taskCodes, billingTaskQueryDto.getType());
                        }
                    } catch (Exception e) {
                        if (null != taskCodes && taskCodes.size() > 0) {
                            //所有账单生成完毕，任务更新为完成状态
                            updateTaskStatus(BillingTaskStatus.SUSPEND, taskCodes, billingTaskQueryDto.getType());
                            List<Integer> suppliers = billingTaskQueryDto.getCustomerIds();
                            if (suppliers != null && suppliers.size() > 0) {
                                for (int supplier : suppliers) {
                                    deleteBillingAndOrder(taskCodes, billingTaskQueryDto.getType(), supplier);
                                }
                            }
                        }
                        e.printStackTrace();
                    }
                }
            });
        } else {
            //所选时间段内没有订单
            throw Exceptions.bizException(ErrorCodes.ERROR_FINANCIAL_GENERATE_ORDER_NOT_EXIST);
        }
        return taskCode;
    }

    /**
     * 账单周期内汇率判断
     *
     * @param billingTaskQueryDto
     */
    private void isExchangeRateEror(BillingTaskQueryDto billingTaskQueryDto) {
        List<OrdServiceBill> ordServiceBills = ordServiceBillService.getOrderNotExchangeRateByCustomerIdAndCreateTime(billingTaskQueryDto.getCustomerIds(), billingTaskQueryDto.getStartEffectTime(), billingTaskQueryDto.getEndEffectTime(), billingTaskQueryDto.getType());
        if (null != ordServiceBills && ordServiceBills.size() > 0) {
            Set<String> exchangeRateSet = new HashSet<>();
            for (OrdServiceBill ordServiceBill : ordServiceBills) {
                exchangeRateSet.add(ordServiceBill.getCustCurrencyCode());
            }
            if (exchangeRateSet.size() > 0) {
                //所选时间段内没有订单
                String errorRate = StringUtils.join(exchangeRateSet, ",");
                throw Exceptions.bizException(ErrorCodes.ERROR_FINANCIAL_GENERATE_EXCHANGE_RATE_ERROR, errorRate);
            }
        }
    }

    /**
     * 删除任务下账单和订单
     *
     * @param taskCodes
     */
    private void deleteBillingAndOrder(List<String> taskCodes, String type, Integer supplier) {
        //删除任务下的所有账单
        billingService.batchDeleteByTaskCodes(taskCodes, type);
        //删除账单下所有订单关联
        billingOrderRelService.batchDeleteByTaskCodes(taskCodes, type);
    }

    /**
     * 删除任务下账单和订单
     *
     * @param taskCodes
     */
    private void deleteBillingAndOrderByRegenerate(List<String> taskCodes, String type, Integer supplier) {
        //删除任务下的所有账单
        billingService.batchDeleteByTaskCodes(taskCodes, type);
        //删除账单下所有订单关联
        billingOrderRelService.batchDeleteByTaskCodes(taskCodes, type);
    }

    /**
     * 生成账单操作
     *
     * @param billingTaskQueryDto
     */
    private List<String> generateThread(BillingTaskQueryDto billingTaskQueryDto, String taskCode, Date taskStartTime) {
        List<String> taskCodes = new ArrayList<>();
        try {
            List<Integer> customerIdList = billingTaskQueryDto.getCustomerIds();
            //
            List<BillingGenerateDto> ordServiceBillList = populateOrderList(customerIdList, billingTaskQueryDto.getStartEffectTime(), billingTaskQueryDto.getEndEffectTime(), billingTaskQueryDto.getType());
            //已经生成
            List<BillingGenerateDto> ordServiceBillListGenerated = populateOrderListGenerated(customerIdList, billingTaskQueryDto.getStartEffectTime(), billingTaskQueryDto.getEndEffectTime(), billingTaskQueryDto.getType());
            //保存任务
            saveTask(taskCode, taskStartTime, billingTaskQueryDto, customerIdList, ordServiceBillList, ordServiceBillListGenerated, billingTaskQueryDto.getType());
            taskCodes.add(taskCode);
            //计算账单
            if (null != customerIdList && customerIdList.size() > 0) {
                for (Integer customerId : customerIdList) {
                    generateBillOperation(billingTaskQueryDto, taskCode, customerId);
                }
            } else {
                generateBillOperation(billingTaskQueryDto, taskCode, null);
            }
        } catch (Exception e) {
            //出现异常，将任务状态设置为异常
//            updateTaskStatus(BillingTaskStatus.SUSPEND, taskCodes);
            updateBillingTask(taskCode, billingTaskQueryDto.getType());
            List<Integer> suppliers = billingTaskQueryDto.getCustomerIds();
            if (suppliers != null && suppliers.size() > 0) {
                for (int supplier : suppliers) {
                    deleteBillingAndOrder(taskCodes, billingTaskQueryDto.getType(), supplier);
                }
            }
            taskCodes = null;
            e.printStackTrace();
        }
        return taskCodes;
    }

    /**
     * 更新任务订单数量和客户数量
     *
     * @param taskCode
     */
    private void updateBillingTask(String taskCode, String type) {
        BillingTask billingTask = findByTaskCode(taskCode, type);
        if (null != billingTask) {
            Date now = dao.getDbDate();
            billingTask.setOrderQuantity(0);
            billingTask.setCompleteOrderQuantity(0);
            billingTask.setSkippedOrderQuantity(0);
            billingTask.setCompleteOrderQuantity(0);
            billingTask.setCompleteCustomerQuantity(0);
            billingTask.setSkippedCustomerQuantity(0);
            billingTask.setTaskStatus(BillingTaskStatus.SUSPEND);
            billingTask.setTaskEndTime(now);
            updateBillingTask(billingTask);
        }
    }

    /**
     * 任务异常，修改任务状态
     *
     * @param taskStatus
     * @param taskCodes
     */
    @Override
    public void updateTaskStatus(BillingTaskStatus taskStatus, List<String> taskCodes, String type) {
        Date now = dao.getDbDate();
        ParamData paramData = new ParamData();
        paramData.put("taskStatus", taskStatus);
        paramData.put("taskEndTime", now);
        paramData.put("taskCodes", taskCodes);
        paramData.put("type", type);
        dao.update(getSqlName("updateTaskStatus"), paramData);
    }

    /**
     * 账单任务详情
     *
     * @param taskCode
     */
    @Override
    public BillingDetailDto billingTaskDetail(String taskCode, String type) {
        ParamData paramData = new ParamData();
        paramData.put("taskCode", taskCode);
        paramData.put("type", type);
        return (BillingDetailDto) dao.findForObject(getSqlName("billingTaskDetail"), paramData);
    }

    /**
     * 修改已经生成账单的客户数量和订单数量
     *
     * @param taskCode
     * @param completeOrderQuantity
     */
    @Override
    public void updateTaskCustomerComplete(String taskCode, Integer completeOrderQuantity, String type) {
        BillingTask billingTask = findByTaskCode(taskCode, type);
        if (null != billingTask) {
            Integer completeCustomers = billingTask.getCompleteCustomerQuantity() == null ? Integer.valueOf(0) : billingTask.getCompleteCustomerQuantity();
            Integer completeOrders = billingTask.getCompleteOrderQuantity() == null ? Integer.valueOf(0) : billingTask.getCompleteOrderQuantity();
            billingTask.setCompleteCustomerQuantity(completeCustomers + 1);
            billingTask.setCompleteOrderQuantity(completeOrders + completeOrderQuantity);
            dao.update(getSqlName("updateSelective"), billingTask);
        }
    }

    /**
     * 保存任务
     *
     * @param taskCode
     * @param taskStartTime
     * @param billingTaskQueryDto
     * @param customerIdList
     * @param ordServiceBillList
     * @param ordServiceBillListGenerated
     * @return
     */
    private String saveTask(String taskCode, Date taskStartTime, BillingTaskQueryDto billingTaskQueryDto, List<Integer> customerIdList, List<BillingGenerateDto> ordServiceBillList, List<BillingGenerateDto> ordServiceBillListGenerated, String type) {
        //保存任务
        BillingTask billingTask = new BillingTask();
        if (null != customerIdList && customerIdList.size() > 0) {
            billingTask.setCustomerId(StringUtils.join(customerIdList, ","));
        }
        billingTask.setDeleted(false);
        if (null != ordServiceBillList) {
            billingTask.setOrderQuantity(ordServiceBillList.size());
            if (null != ordServiceBillListGenerated) {
                billingTask.setOrderQuantity(ordServiceBillList.size() + ordServiceBillListGenerated.size());
                billingTask.setSkippedOrderQuantity( ordServiceBillListGenerated.size());
            }
        }
        if (null != customerIdList && customerIdList.size() > 0) {
            billingTask.setCustomerQuantity(customerIdList.size());
        } else {
            billingTask.setCustomerQuantity(countCustomers(ordServiceBillList));
        }
        billingTask.setTaskCode(taskCode);
        billingTask.setTaskStartTime(taskStartTime);
        billingTask.setStartEffectTime(billingTaskQueryDto.getStartEffectTime());
        billingTask.setEndEffectTime(billingTaskQueryDto.getEndEffectTime());
        billingTask.setIsRegenerate(false);
        billingTask.setTaskStatus(BillingTaskStatus.PROCESSING);
        billingTask.setType(type);
        billingTask.setRegenerateTimes(0);
        dao.save(getSqlName("insertSelective"), billingTask);
        return taskCode;
    }

    /**
     * 生成任务编码-年月日各两位+当日三位流水
     *
     * @return
     */
    private synchronized String generateTaskCode() {
        //数据库当前时间
        Date now = dao.getDbDate();
        //年月日各两位
        String prefix = DateUtils.formatDateForBillingTaskCode(now);
        //最三位流水
        String suffix = "001";
        //获取数据库最新
        String lastTaskCode = getLastTaskCode(prefix);
        if (!com.sz.common.base.utils.StringUtils.isEmpty(lastTaskCode)) {
            suffix = lastTaskCode.substring(prefix.length());
            suffix = populateSuffix(suffix, 3);
        }
        String newTaskCod = prefix + suffix;
        //新的任务编码是否已经存在
        String newTaskCodeIsExist = getLastTaskCode(newTaskCod);
        if (!com.sz.common.base.utils.StringUtils.isEmpty(newTaskCodeIsExist)) {
            generateTaskCode();
        }
        return prefix + suffix;
    }

    /**
     * 不够位数的在前面补0，保留num的长度位数字
     *
     * @param code
     * @return
     */
    private static String populateSuffix(String code, int num) {
        return String.format("%0" + num + "d", Integer.parseInt(code) + 1);
    }

    /**
     * 数据库当天最新任务编码
     *
     * @param prefix
     * @return
     */
    private String getLastTaskCode(String prefix) {
        ParamData paramData = new ParamData();
        paramData.put("prefix", prefix);
        return (String) dao.findForObject(getSqlName("getLastTaskCode"), paramData);
    }

    /**
     * 生成具体账单
     *
     * @param billingTaskQueryDto
     * @param taskCode
     * @param customerId
     */
    private void generateBillOperation(BillingTaskQueryDto billingTaskQueryDto, String taskCode, Integer customerId) {
        BillingTaskDto billingTaskDto = new BillingTaskDto();
        BeanUtils.copyProperties(billingTaskQueryDto, billingTaskDto);
        billingTaskDto.setCustomerId(customerId);
        billingTaskDto.setTaskCode(taskCode);
        billingService.generateBill(billingTaskDto);
    }

    /**
     * 计算要生成的账单中的客户数量
     *
     * @param ordServiceBillList
     */
    private Integer countCustomers(List<BillingGenerateDto> ordServiceBillList) {
        Set<Integer> customers = new HashSet<>();
        if (null != ordServiceBillList && ordServiceBillList.size() > 0) {
            for (BillingGenerateDto billingGenerateDto : ordServiceBillList) {
                customers.add(billingGenerateDto.getCustomerId());
            }
        }
        return customers.size();
    }

    /**
     * 重新生成账单
     *
     * @param taskCodes
     */
    @Override
    public void regenerate(List<String> taskCodes, String type, List<Integer> suppliers) {
        //正在任务列表或者草稿之后状态的账单都不能生成
        checkTaskStatusPreDelete(taskCodes);
        //删除任务下的所有账单
        billingService.batchDeleteByTaskCodes(taskCodes, type);
        //删除账单下所有订单关联
        billingOrderRelService.batchDeleteByTaskCodes(taskCodes, type);
        if (suppliers != null && suppliers.size() > 0) {
            for (int supplier : suppliers) {
                deleteBillingAndOrderByRegenerate(taskCodes, type, supplier);
            }
        }
        // deleteBillingAndOrderByRegenerate(taskCodes,type);
        //修改任务状态
        updateTaskStatusByTaskCodes(taskCodes, type);
        //创建一个线程池
        ExecutorService cachedThreadPool = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                60L, TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>());

        cachedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    regenerateThread(taskCodes, type, suppliers);
                    //所有账单生成完毕，任务更新为完成状态
                    updateTaskStatus(BillingTaskStatus.COMPLETED, taskCodes, type);
                } catch (Exception e) {
                    //所有账单生成完毕，任务更新为完成状态
                    updateTaskStatus(BillingTaskStatus.SUSPEND, taskCodes, type);
                    //deleteBillingAndOrder(taskCodes,type);
                    if (suppliers != null && suppliers.size() > 0) {
                        for (int supplier : suppliers) {
                            deleteBillingAndOrderByRegenerate(taskCodes, type, supplier);
                        }
                    }
                    //deleteBillingAndOrderByRegenerate(taskCodes,type);
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 重新生成账单
     *
     * @param taskCodes
     */
    private void regenerateThread(List<String> taskCodes, String type, List<Integer> suppliers) {
        try {
            //获取任务中的客户，账单周期时间
            List<BillingTask> billingTaskList = findByTaskCodes(taskCodes);
            if (null != billingTaskList && billingTaskList.size() > 0) {
                for (BillingTask billingTask : billingTaskList) {
                    String customerIds = billingTask.getCustomerId();
                    if (!com.sz.common.base.utils.StringUtils.isEmpty(customerIds)) {
                        String[] customerList = customerIds.split(",");
                        if (null != customerList && customerList.length > 0) {
                            for (String customerId : customerList) {
                                billingService.regenerate(billingTask.getTaskCode(), Integer.valueOf(customerId), billingTask.getStartEffectTime(), billingTask.getEndEffectTime(), type);
                            }
                        } else {
                            billingService.regenerate(billingTask.getTaskCode(), null, billingTask.getStartEffectTime(), billingTask.getEndEffectTime(), type);
                        }
                    } else {
                        billingService.regenerate(billingTask.getTaskCode(), null, billingTask.getStartEffectTime(), billingTask.getEndEffectTime(), type);
                    }
                }
            }
        } catch (Exception e) {
            updateTaskStatus(BillingTaskStatus.SUSPEND, taskCodes, type);
            for (int supplier : suppliers) {
                deleteBillingAndOrder(taskCodes, type, supplier);
            }
            // deleteBillingAndOrder(taskCodes,type);
        }
    }

    /**
     * 重新生成时更新任务状态
     *
     * @param taskCodes
     */
    private void updateTaskStatusByTaskCodes(List<String> taskCodes, String type) {
        if (null != taskCodes && taskCodes.size() > 0) {
            for (String taskCode : taskCodes) {
                BillingTask billingTask = findByTaskCode(taskCode, type);
                if (null != billingTask) {
                    String customerIds = billingTask.getCustomerId();
                    List<Integer> customerIdList = new ArrayList<>();
                    if (!com.sz.common.base.utils.StringUtils.isEmpty(customerIds)) {
                        String[] customerList = customerIds.split(",");
                        if (null != customerList && customerList.length > 0) {
                            for (String customerId : customerList) {
                                customerIdList.add(Integer.valueOf(customerId));
                            }
                        }
                    }
                    List<BillingGenerateDto> ordServiceBillList = populateOrderList(customerIdList, billingTask.getStartEffectTime(), billingTask.getEndEffectTime(), type);
                    List<BillingGenerateDto> ordServiceBillListGenerated = populateOrderListGenerated(customerIdList, billingTask.getStartEffectTime(), billingTask.getEndEffectTime(), type);
                    //更新任务数据
                    updateReTaskForReGenerate(taskCode, customerIdList, ordServiceBillList, ordServiceBillListGenerated);
                }

            }
        }
    }

    /**
     * 未生账单列表
     *
     * @param customerIdList
     * @param startEffectTime
     * @param endEffectTime
     * @return
     */
    private List<BillingGenerateDto> populateOrderList(List<Integer> customerIdList, Date startEffectTime, Date endEffectTime, String type) {
        List<BillingGenerateDto> ordServiceBillList = null;
        if (null != customerIdList && customerIdList.size() > 0) {
            ordServiceBillList = ordServiceBillService.getOrderForBillingTask(customerIdList, startEffectTime, endEffectTime, false, type);
        } else {
            if (TrdConstants.BillType.PAYABLE.equals(type)) {
                ordServiceBillList = ordServiceBillService.getOrderByCustomerAndCreateTime(null, startEffectTime, endEffectTime, false);
            } else {
                ordServiceBillList = ordServiceBillService.getOrderBySupplierAndCreateTime(null, startEffectTime, endEffectTime, false);
            }

        }
        return ordServiceBillList;
    }

    /**
     * 已经生账单列表
     *
     * @param customerIdList
     * @param startEffectTime
     * @param endEffectTime
     * @return
     */
    private List<BillingGenerateDto> populateOrderListGenerated(List<Integer> customerIdList, Date startEffectTime, Date endEffectTime, String type) {
        List<BillingGenerateDto> ordServiceBillListGenerated = null;
        if (null != customerIdList && customerIdList.size() > 0) {
            ordServiceBillListGenerated = ordServiceBillService.getOrderForBillingTask(customerIdList, startEffectTime, endEffectTime, true, type);
        } else {
            if (TrdConstants.BillType.PAYABLE.equals(type)) {
                ordServiceBillListGenerated = ordServiceBillService.getOrderByCustomerAndCreateTime(null, startEffectTime, endEffectTime, true);
            } else {
                ordServiceBillListGenerated = ordServiceBillService.getOrderBySupplierAndCreateTime(null, startEffectTime, endEffectTime, true);
            }
        }
        return ordServiceBillListGenerated;
    }


    /**
     * 更新任务数据
     *
     * @param taskCode
     * @param customerIdList
     * @param ordServiceBillList
     */
    private void updateReTaskForReGenerate(String taskCode, List<Integer> customerIdList, List<BillingGenerateDto> ordServiceBillList, List<BillingGenerateDto> ordServiceBillListGenerated) {
        //任务开始时间
        Date taskStartTime = dao.getDbDate();
        BillingTask billingTask = new BillingTask();
        billingTask.setTaskCode(taskCode);
        billingTask.setTaskStatus(BillingTaskStatus.PROCESSING);
        billingTask.setTaskStartTime(taskStartTime);
        billingTask.setCustomerQuantity(null == customerIdList ? 0 : customerIdList.size());
        billingTask.setCompleteCustomerQuantity(0);
        billingTask.setSkippedCustomerQuantity(0);
        billingTask.setSkippedCustomerList(null);
        billingTask.setCompleteOrderQuantity(0);
        billingTask.setSkippedOrderQuantity(0);
        if (null != ordServiceBillList) {
            billingTask.setOrderQuantity(ordServiceBillList.size());
            if (null != ordServiceBillListGenerated) {
                billingTask.setOrderQuantity(ordServiceBillList.size() + ordServiceBillListGenerated.size());
            }
        } else {
            billingTask.setOrderQuantity(0);
        }
        if (null != customerIdList && customerIdList.size() > 0) {
            billingTask.setCustomerQuantity(customerIdList.size());
        } else {
            billingTask.setCustomerQuantity(countCustomers(ordServiceBillList));
        }
        dao.update(getSqlName("updateTaskStatusForRegenerate"), billingTask);
    }

    /**
     * 正在任务列表或者草稿之后状态的账单都不能生成
     *
     * @param taskCodes
     */
    private void checkTaskStatusPreDelete(List<String> taskCodes) {
        List<BillingTask> billingTasks = findByTaskCodes(taskCodes);
        for (BillingTask billingTask : billingTasks) {
            //正在任务列表或者草稿之后状态的账单都不能生成
            if (!billingTask.getTaskStatus().getCode().equals(BillingTaskStatus.SUSPEND.getCode())) {
                throw Exceptions.bizException(ErrorCodes.ERROR_FINANCIAL_SUSPEND_CAN_REGENERATE);
            }
        }
    }

    /**
     * 根据任务编码获取任务
     *
     * @param taskCodes
     * @return
     */
    @Override
    public List<BillingTask> findByTaskCodes(List<String> taskCodes) {
        ParamData paramData = new ParamData();
        paramData.put("taskCodes", taskCodes);
        return dao.findForList(getSqlName("findByTaskCodes"), paramData, BillingTask.class);
    }

    /**
     * 根据任务编码获取任务
     *
     * @param taskCode
     * @return
     */
    @Override
    public BillingTask findByTaskCode(String taskCode, String type) {
        ParamData paramData = new ParamData();
        paramData.put("taskCode", taskCode);
        paramData.put("type", type);
        return (BillingTask) dao.findForObject(getSqlName("findByTaskCode"), paramData);
    }

    /**
     * 账单任务列表
     *
     * @param params
     * @return
     */
    @Override
    public QResultDto findBillingTaskList(QueryParams params) {
        ParamData pd = convertQueryParams(params);
        //根据条件获取账单列表
        List<BillingTaskDto> billTasks = dao.findForList(getSqlName("findTaskByFilterListPage"), pd, BillingTaskDto.class);
        return new QResultDto(billTasks, pd.getPagination());
    }

    /**
     * 所有账单任务状态
     *
     * @return 顺序： 处理中；已完成；异常
     */
    @Override
    public List<CommonModel> getAllTaskStatus() {
        List<CommonModel> list = Lists.newArrayList();
        for (BillingTaskStatus billingTaskStatus : BillingTaskStatus.values()) {
            CommonModel dto = new CommonModel(billingTaskStatus.name(), billingTaskStatus.getName());
            list.add(dto);
        }
        return list;
    }

    /**
     * 更新账单任务
     *
     * @param billingTask
     */
    @Override
    public void updateBillingTask(BillingTask billingTask) {
        dao.update(getSqlName("updateSelective"), billingTask);
    }

    /**
     * 验证时间段是否正确
     *
     * @param billingTaskQueryDto
     */
    private void validateStartEndTime(BillingTaskQueryDto billingTaskQueryDto) {
        //判断查询订单的时间段参数是否存正确
        if (null == billingTaskQueryDto || null == billingTaskQueryDto.getStartEffectTime() || null == billingTaskQueryDto.getEndEffectTime()) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL);
        }
    }

    @Override
    protected String getMapperNamespace() {
        return "com.sz.biz.logistics.bill.entity.BillingTaskMapper";
    }
}
